import sys
from abc import ABC, abstractmethod
import httpx
import secrets
from urllib.parse import urlencode
from typing import Dict, Any


class ThirdPartyLoginFactory(ABC):
    @abstractmethod
    def get_auth_url(self):
        pass

    @abstractmethod
    async def handle_callback(self, code: str, state: str):
        pass


class DingdingLogin(ThirdPartyLoginFactory):
    """钉钉OAuth登录实现"""

    def __init__(self):
        # 钉钉OAuth配置 - 生产环境请使用环境变量
        self.app_key = "dingictzzf7p6xl0dktk"
        self.app_secret = "1KIHc75jev24l6N0fSiFEFMcn8qkY1pea1BfpLpHI2iI7rQWno8f3tgzCEAjnV4v"
        self.redirect_uri = "http://localhost:5174/dingtalk-callback"  # 正确的钉钉回调地址
        self.auth_url = "https://login.dingtalk.com/oauth2/auth"
        self.token_url = "https://api.dingtalk.com/v1.0/oauth2/userAccessToken"
        self.user_info_url = "https://api.dingtalk.com/v1.0/contact/users/me"

    def get_auth_url(self) -> Dict[str, str]:
        """生成钉钉OAuth授权URL"""
        state = secrets.token_urlsafe(32)

        params = {
            "redirect_uri": self.redirect_uri,
            "response_type": "code",
            "client_id": self.app_key,
            "scope": "openid",
            "state": state,
            "prompt": "consent"
        }

        auth_url = f"{self.auth_url}?{urlencode(params)}"
        return {
            "auth_url": auth_url,
            "state": state
        }

    async def handle_callback(self, code: str, state: str) -> Dict[str, Any]:
        """处理钉钉OAuth回调"""
        try:
            async with httpx.AsyncClient() as client:
                # 第一步：使用code获取access_token
                token_data = {
                    "clientId": self.app_key,
                    "clientSecret": self.app_secret,
                    "code": code,
                    "grantType": "authorization_code"
                }

                headers = {
                    "Content-Type": "application/json"
                }

                token_response = await client.post(self.token_url, json=token_data, headers=headers)
                token_result = token_response.json()

                if "error" in token_result or "errorCode" in token_result:
                    raise Exception(f"DingTalk token error: {token_result}")

                if "accessToken" not in token_result:
                    raise Exception(f"DingTalk token response missing accessToken: {token_result}")

                access_token = token_result["accessToken"]

                # 第二步：使用access_token获取用户信息
                user_headers = {
                    "x-acs-dingtalk-access-token": access_token,
                    "Content-Type": "application/json"
                }

                user_response = await client.get(self.user_info_url, headers=user_headers)
                user_result = user_response.json()

                if "error" in user_result or "errorCode" in user_result:
                    raise Exception(f"DingTalk API error: {user_result}")

                user_data = user_result
                print(f"🔍 钉钉API返回的用户数据: {user_data}")

                # 尝试多种方式获取用户ID
                user_id = (
                    user_data.get("openId") or
                    user_data.get("unionId") or
                    user_data.get("id") or
                    user_data.get("userId") or
                    ""
                )

                # 如果用户ID为空，使用access_token的前32位作为临时ID
                if not user_id:
                    print(f"⚠️ 钉钉用户ID为空，使用access_token前32位作为临时ID")
                    user_id = access_token[:32] if access_token else "temp_user_id"

                print(f"✅ 最终用户ID: {user_id}")

                user_info = {
                    "id": user_id,
                    "name": user_data.get("nick", user_data.get("name", "钉钉用户")),
                    "avatar_url": user_data.get("avatarUrl", user_data.get("avatar", "")),
                    "mobile": user_data.get("mobile"),
                    "email": user_data.get("email")
                }

                return {
                    "success": True,
                    "user": user_info,
                    "access_token": access_token,
                    "platform": "dingtalk"
                }

        except Exception as e:
            return {
                "success": False,
                "error": str(e),
                "platform": "dingtalk"
            }


class GiteeLogin(ThirdPartyLoginFactory):
    """Gitee OAuth登录实现"""

    def __init__(self):
        # Gitee OAuth配置 - 生产环境请使用环境变量
        self.client_id = "dcbbce9c434c09841ba9195e0365230223003055decf61de36ca0a7fefd2fdb1"
        self.client_secret = "8775338b46455bb6d2b93878fb08a6e678637d7b74bb6636760626daf46a5907"
        self.redirect_uri = "http://localhost:5174/gitee-callback"  # 正确的Gitee回调地址
        self.scope = "user_info"
        self.auth_url = "https://gitee.com/oauth/authorize"
        self.token_url = "https://gitee.com/oauth/token"
        self.user_info_url = "https://gitee.com/api/v5/user"

    def get_auth_url(self) -> Dict[str, str]:
        """生成Gitee OAuth授权URL"""
        state = secrets.token_urlsafe(32)

        params = {
            "client_id": self.client_id,
            "redirect_uri": self.redirect_uri,
            "response_type": "code",
            "scope": self.scope,
            "state": state
        }

        auth_url = f"{self.auth_url}?{urlencode(params)}"
        return {
            "auth_url": auth_url,
            "state": state
        }

    async def handle_callback(self, code: str, state: str) -> Dict[str, Any]:
        """处理Gitee OAuth回调"""
        try:
            print(f"🔍 处理Gitee回调: code={code}, state={state}")

            async with httpx.AsyncClient() as client:
                # 第一步：使用code获取access_token
                token_data = {
                    "grant_type": "authorization_code",
                    "code": code,
                    "client_id": self.client_id,
                    "client_secret": self.client_secret,
                    "redirect_uri": self.redirect_uri
                }

                print(f"📡 获取Gitee访问令牌...")
                token_response = await client.post(self.token_url, data=token_data)
                token_result = token_response.json()
                print(f"📥 Token响应: {token_result}")

                if "error" in token_result:
                    raise Exception(f"Gitee token error: {token_result}")

                access_token = token_result["access_token"]
                print(f"✅ 获取Gitee访问令牌成功: {access_token[:20]}...")

                # 第二步：使用access_token获取用户信息
                headers = {"Authorization": f"token {access_token}"}
                print(f"📡 获取Gitee用户信息...")
                user_response = await client.get(f"{self.user_info_url}?access_token={access_token}")
                user_data = user_response.json()
                print(f"📥 用户信息响应: {user_data}")

                if "message" in user_data:
                    raise Exception(f"Gitee API error: {user_data}")

                print(f"✅ Gitee API调用成功: {user_data}")

                user_info = {
                    "id": str(user_data["id"]),  # Gitee API返回整数ID，转换为字符串
                    "login": user_data["login"],
                    "name": user_data["name"],
                    "avatar_url": user_data["avatar_url"],
                    "email": user_data.get("email"),
                    "bio": user_data.get("bio"),
                    "blog": user_data.get("blog"),
                    "company": user_data.get("company"),
                    "location": user_data.get("location"),
                    "public_repos": user_data.get("public_repos", 0),
                    "followers": user_data.get("followers", 0),
                    "following": user_data.get("following", 0)
                }

                return {
                    "success": True,
                    "user": user_info,
                    "access_token": access_token,
                    "platform": "gitee"
                }

        except Exception as e:
            return {
                "success": False,
                "error": str(e),
                "platform": "gitee"
            }


class ThirdPartyLoginManager:
    """第三方登录管理器"""

    def __init__(self):
        self.login_classes = {
            "dingtalk": DingdingLogin,
            "gitee": GiteeLogin
        }

    def get_login_instance(self, platform: str):
        """获取第三方登录实例"""
        if platform in self.login_classes:
            return self.login_classes[platform]()
        return None
